﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Bootloader.Services
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;

    public class FileParser
    {
        // 刷写文件类
        public class FlashFile
        {
            public string FilePath;
            public uint StartAddr;
            public byte[] Data;
        }

        public class SigFile
        {
            public string FilePath;
            public List<Byte[]> Data;
        }

        // 解析s19文件类
        public static class S19Parser
        {
            /// <summary>
            /// 解析 S19 文件，返回起始地址和完整的二进制数据（按地址连续排列）
            /// </summary>
            /// <param name="filePath">S19 文件路径</param>
            /// <returns>(StartAddress, DataBytes)</returns>

            public static FlashFile ParseFile(string filePath)
            {
                var lines = File.ReadAllLines(filePath);
                var memory = new Dictionary<uint, byte>();
                uint? explicitStartAddress = null;

                foreach (var line in lines)
                {
                    if (string.IsNullOrWhiteSpace(line)) continue;
                    string l = line.Trim();

                    // 基本格式检查
                    if (l.Length < 4 || !l.StartsWith("S")) continue;

                    string hexData = l.Substring(1); // 移除 'S'
                    if (hexData.Length < 4) continue;

                    // 解析记录类型
                    if (!byte.TryParse(hexData[0].ToString(), System.Globalization.NumberStyles.HexNumber, null, out byte recordType))
                        continue;

                    // 确定地址字节数
                    int addrBytes;
                    switch (recordType)
                    {
                        case 0:
                        case 1:
                        case 9:
                            addrBytes = 2;
                            break;
                        case 2:
                        case 8:
                            addrBytes = 3;
                            break;
                        case 3:
                        case 7:
                            addrBytes = 4;
                            break;
                        default:
                            addrBytes = 0;
                            break;
                    }
                    if (addrBytes == 0) continue; // 不支持的类型

                    // 解析 ByteCount
                    if (hexData.Length < 3) continue;
                    if (!int.TryParse(hexData.Substring(1, 2), System.Globalization.NumberStyles.HexNumber, null, out int byteCount))
                        continue;

                    // 验证总长度：hexData 应为 1（类型已去）+ 2（ByteCount）+ byteCount*2
                    int expectedHexLength = 1 + 2 + byteCount * 2;
                    if (hexData.Length != expectedHexLength)
                        continue;

                    // 校验和验证：对 hexData.Substring(1) 的所有字节求和，低8位应为 0
                    uint checksumSum = 0;
                    string payload = hexData.Substring(1); // 从 ByteCount 开始
                    for (int i = 0; i < payload.Length; i += 2)
                    {
                        checksumSum += Convert.ToByte(payload.Substring(i, 2), 16);
                    }
                    if ((checksumSum & 0xFF) != 0xFF)
                        throw new InvalidOperationException("s19文件校验值错误");

                    // 解析地址
                    string addrHex = hexData.Substring(3, addrBytes * 2);
                    if (!uint.TryParse(addrHex, System.Globalization.NumberStyles.HexNumber, null, out uint address))
                        throw new InvalidOperationException("s19地址解析失败");

                    // 仅 S1/S2/S3 包含有效数据
                    if (recordType >= 1 && recordType <= 3)
                    {
                        int dataStartIndex = 3 + addrBytes * 2;
                        int dataEndIndex = hexData.Length - 2; // 最后2字符是校验和
                        if (dataEndIndex > dataStartIndex)
                        {
                            string dataHex = hexData.Substring(dataStartIndex, dataEndIndex - dataStartIndex);
                            int dataByteCount = dataHex.Length / 2;
                            for (int i = 0; i < dataByteCount; i++)
                            {
                                byte b = Convert.ToByte(dataHex.Substring(i * 2, 2), 16);
                                memory[address + (uint)i] = b;
                            }
                        }
                    }

                }

                if (memory.Count == 0)
                    throw new InvalidOperationException("s19文件无有效数据");

                uint minAddr = memory.Keys.Min();
                uint maxAddr = memory.Keys.Max();
                uint startAddress = explicitStartAddress ?? minAddr;

                // 构建连续数据块（从 minAddr 到 maxAddr）
                int length = (int)(maxAddr - minAddr + 1);
                byte[] data = new byte[length];
                for (int i = 0; i < length; i++)
                {
                    uint addr = minAddr + (uint)i;
                    data[i] = memory.TryGetValue(addr, out byte b) ? b : (byte)0xFF;
                }

                return new FlashFile
                {
                    FilePath = filePath,
                    StartAddr = startAddress,
                    Data = data
                };
            }
        }

        // 解析sig文件类
        public static class SigFileParser
        {
            /// <summary>
            /// 解析 .sig 文件内容并返回 FlashFile 对象
            /// </summary>
            /// <param name="filePath">.sig 文件路径</param>
            /// <returns>FlashFile 对象，包含文件名、起始地址（默认0）和数据</returns>
            public static SigFile ParseFromFile(string filePath)
            {
                var sigFile = new SigFile
                {
                    FilePath = Path.GetFileName(filePath),
                    Data = new List<byte[]>()
                };

                using (var reader = new StreamReader(filePath, System.Text.Encoding.UTF8))
                {
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        // 跳过空行
                        if (string.IsNullOrWhiteSpace(line)) continue;

                        // 分割逗号，去除空格和换行
                        string[] parts = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        var bytes = new List<byte>();

                        for (int i = 0; i < parts.Length; i++)
                        {
                            string token = parts[i].Trim();

                            // 必须以 "0x" 开头（不区分大小写）
                            if (!token.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                            {
                                throw new FormatException($"sig文件格式错误，未以0x开头: {token}");
                            }

                            // 提取 "0x" 后的部分
                            string hexPart = token.Substring(2);

                            // 允许空（但实际不应出现）
                            if (string.IsNullOrEmpty(hexPart))
                            {
                                throw new FormatException("sig文件为空");
                            }

                            // 尝试解析为 byte（支持 1~2 位十六进制，如 0xA 或 0xAB）
                            if (!byte.TryParse(hexPart, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out byte b))
                            {
                                throw new FormatException($"sig文件出现非十六进制数: {hexPart}");
                            }

                            bytes.Add(b);
                        }

                        // 将当前行解析的数据作为一个字节数组添加到Data列表
                        if (bytes.Count > 0)
                        {
                            sigFile.Data.Add(bytes.ToArray());
                        }
                    }
                }
                return sigFile;
            }

        }
    }
}